import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/**
 * Created with IntelliJ IDEA.
 * Description:Tcp版本的回显服务器
 * Author: WJW
 * Date: 2024-08-24
 * Time: 17:50
 */
public class TcpEchoServer {
    private ServerSocket serverSocket = null;

    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动！");
        //线程池
        ExecutorService poll = Executors.newCachedThreadPool();
        while (true){
            //通过accept方法来“接听电话”才能实现通信
            Socket clientSocket =  serverSocket.accept();
           //多线程服务器
//            Thread t = new Thread(()->{
//                processConnoction(clientSocket);
//            });
//            t.start();

            //线程池服务器
            poll.submit(new Runnable() {
                @Override
                public void run() {
                    processConnoction(clientSocket);
                }
            });
        }
    }

    private void processConnoction(Socket clientSocket) {
        System.out.printf("[%s:%d] 客户端上线！\n",clientSocket.getInetAddress(),clientSocket.getPort());
        //循环读取客户端的请求并相应
        try(InputStream inputStream = clientSocket.getInputStream();
           OutputStream outputStream = clientSocket.getOutputStream()){
            while(true){

                Scanner scanner = new Scanner(inputStream);
                if(!scanner.hasNext()){
                    //读取完毕 客户端断开连接就会产生读取完毕
                    System.out.printf("[%s:%d] 客户端下线！\n",clientSocket.getInetAddress(),clientSocket.getPort());
                    break;
                }
            //1.读取请求并解析，注意这里的隐藏约定，next读到的时候要读到空白符才会结束
            //因此就要客户端发来的请求必须带有空白符结尾，比如\n或者空格
            String request = scanner.next();
            //2.根据请求计算响应
            String response = process(request);
            //3.把响应返回给客户端
            //通过这种方式可以歇会，但是这种方式不方便给返回的响应中添加\n
            //    outputStream.write(response.getBytes(),0,response.getBytes().length);
            //也可以给outPutStream套上一层，完成更方便的写入
                PrintWriter printWriter = new PrintWriter(outputStream);
                printWriter.println(response);
                printWriter.flush();

                System.out.printf("[%s:%d] rep: %s,resp:%s\n",clientSocket.getInetAddress(), clientSocket.getPort(),request,response);

            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public String process(String request) {
         return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(9090);
        server.start();
    }
}
